參考文件:
webpacker
Rails版本5.1以上可以直接創造帶有webpack的新專案$ rails new rails-vue-todolist --skip-turbolinks --skip-spring --webpack=vue
$ cd rails-vue-todolist
先快速建立todolist$ rails g scaffold Todolist item:string
$ bundle install
設定router1
root "todolists#index"
測試有沒有成功1
<%= javascript_pack_tag 'hello_vue' %>
更新todolist/index1
2<div id="hello"></div>
...
$ rails s
到首頁刷新頁面應該就會有了,如果有出現:You may need an appropriate loader to handle this file type.
可以嘗試下下面三個指令$ bundle update webpacker
$ yarn upgrade @rails/webpacker
$ bundle exec rails webpacker:install:vue
大多會是版本上的問題,如果直接用rails5.1以上應該沒有問題,如果是用其他版本或者是專案升級情況可能要再去查詢下官方log文件。
再來如果玩過Vue.js的人有一種開發模式是把一個id=”app”當作入口,所以我們會有一個主要的main.js
和主要生成vue的app.vue
,此時app/javascript/packs/application.js可以把它當作main.js
,再來怎麼規劃檔案就都可以了。
我們循著上面的作法先改rails view剛剛的application.html.erb的tag1
2
3# 把原本的 <%= javascript_pack_tag 'hello_vue' %> 替換如下
<%= javascript_pack_tag 'application' %>
修改index入口點只留下一行當作vue的入口就好1
<div id="app"></div>
修改packs/application.js1
2
3
4
5
6
7
8
9import Vue from 'vue'
import App from '../app.vue'
document.addEventListener('DOMContentLoaded', () => {
const app = new Vue({
el: "#app",
render: h => h(App)
})
})
現在再重新刷新一次頁面如果有render出Hello Vue!恭喜已經設定好所有一切了!
初創index
接下來我們先直接在app.vue裡面創造假資料做出index畫面:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33<template>
<div>
<h1>Todo Lists</h1>
<table>
<thead>
<tr>
<th>#</th>
<th>Item</th>
</tr>
</thead>
<tbody>
<tr v-for="todo in list" >
<td>{{ todo.id }}</td>
<td>{{ todo.item }}</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
export default {
data: function () {
return {
list: [
{ id: 1, item: "Foo" },
{ id: 2, item: "Bar" }
]
}
}
}
</script>
應該會list出兩個item出來,但我們要去拿rails裡todolists#index的資料,首先我們在rails console新增兩筆:$ rails c
$ Todolist.create(item: "Test1")
$ Todolist.create(item: "Test2")
$ exit
然後如何從vue的methods裡面拿取資料,可以用vue-resource這個套件。$ yarn add vue-resource
然後import在app/javascript/application.js裡:1
2import VueResource from 'vue-resource'
Vue.use(VueResource);
現在修改app.vue1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44<template>
<div>
<h1>Todo Lists</h1>
<table>
<thead>
<tr>
<th>#</th>
<th>Item</th>
</tr>
</thead>
<tbody>
<tr v-for="todo in list" >
<td>{{ todo.id }}</td>
<td>{{ todo.item }}</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
export default {
data: function () {
return {
list: []
}
},
created: function() {
this.fetchTodoLists();
},
methods: {
fetchTodoLists: function() {
const resource = this.$resource('/todolists.json');
resource.get()
.then(response => {
this.list = response.data
});
}
}
}
</script>
應該會出現剛剛在console創的兩筆資料。
component裡面寫css
在webpacker官方文件裡面有規劃資料夾,雖然敘述說會有放js css images的地方但我初創的時候只有放js的資料夾,他的架構如下:
app/javascript:
├── packs:
│ # only webpack entry files here
│ └── application.js
└── src:
│ └── application.css
└── images:
└── logo.svg
照著他的架構創$ mkdir app/javascript/src
$ touch app/javascript/src/application.css
然後在原本rails的application.html.erb加上連結1
<%= stylesheet_pack_tag 'application' %>
就可以在每個.vue檔的component裡面寫css了,例如:1
2
3
4
5
6<style lang="scss">
.link {
color: blue;
cursor: pointer;
}
</style>
引入vue-router
再來跟全端開發一樣,rails的gem歸rails的Gemfile,而webpack的歸package.json(Vue也是在這裡面,只不過rails5.1連著專案一起創webpack的話已經內建Vue了!)。
現在安裝vue-router$ yarn add vue-router
先把router寫在一個js裡面:$ touch app/javascript/packs/router.js
建立routes1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
import todolists_index from './../views/todolist/index.vue'
const router = new VueRouter({
// 使用 HTML 5 模式
mode: 'history',
routes: [
{ path: '/todolists', component: todolists_index },
{ path: '/', redirect: '/todolists' }
]
})
export default router
檔名或變數不要取routes避免產生match error
修改packs/application.js把1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17import Vue from 'vue'
import App from '../app.vue'
import VueResource from 'vue-resource'
Vue.use(VueResource);
import VueRouter from 'vue-router'
Vue.use(VueRouter)
import router from './router.js'
document.addEventListener('DOMContentLoaded', () => {
const app = new Vue({
el: "#app",
router,
render: h => h(App)
})
})
現在創造專給vue的view的資料夾$ mkdir app/javascript/views
再給todolist一個歸類$ mkdir app/javascript/views/todolist
最後先做index檔案,根本來的app.vue一模一樣$ cp app/javascript/app.vue app/javascript/views/todolist/index.vue
最後app.vue簡化如下:1
2
3
4
5
6
7
8
9
10
11<template>
<div>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'app'
}
</script>
就成功import vue-router了!這樣也算是做出前後端分離的概念了,rails去吐api,而vue就專門做前端的東西吧!